package OBSXML;

import Errorhandler.ErrorLogger;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.xml.parsers.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * Læser indhold af en XML fil.
 *
 * @author Børge Bergstrøm
 */
public class XML {

    private final File parent = new File(System.getProperty("user.dir"));
    protected String XMLFileName, path;
    private String logDir = parent + File.separator+"log"+File.separator;
    private String logName = "XMLContentErrors.log";

    /**
     * Henter XML fil
     * 
     * @param path
     * @param XMLFileName
     */
    public XML(String path, String XMLFileName)
    {
        this.path = path;
        this.XMLFileName = XMLFileName;
    }

    /**
     * Indlæser XML fil.
     * 
     * @return File
     */
    protected File XMLFile()
    {
        File file = new File(parent+File.separator+path+File.separator+File.separator+XMLFileName);

        return file;
    }

    /**
     * Læser første noder efter root noden, som er Parent noder.
     * 
     * @return ArrayList<String>
     */
    private ArrayList<String> XMLParents()
    {
        //ArrayList til at holde værdier indlæst fra xml dokument
        ArrayList<String> xmlValues = new ArrayList<String>();
        try
        {
            //Byg fabrik til at læse XML
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();

            //Parse XML
            Document doc = docBuilder.parse(XMLFile());

            // normaliser text
            doc.getDocumentElement().normalize();

            //Hent root navn
            String root = doc.getDocumentElement().getNodeName();

            Element rootElement = doc.getDocumentElement();

            NodeList rl = rootElement.getChildNodes();

            int totalRootNodes = rl.getLength();
            //Find navne på parent
            for(int i = 0;i<rl.getLength(); i++)
            {
                Node firstLevelNode = rl.item(i);

                if(firstLevelNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    Element firstLevelElement = (Element)firstLevelNode;

                    String elementName = firstLevelElement.getNodeName();

                    xmlValues.add(elementName);

                }
            }
        }
        catch(Exception ex)
        {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        }

        for(int x = 0; x<xmlValues.size();x++)
        {
            if(xmlValues.get(x).equals("#text"))
            {
                xmlValues.remove("#text");
            }
        }

        return xmlValues;
    }

    /**
     * Læser Children noderne i en parent node.
     * 
     * @return ArrayList<String>
     */
    private ArrayList<String> XMLChildren()
    {
        //ArrayList til at holde værdier indlæst fra xml dokument
        ArrayList<String> xmlValues = new ArrayList<String>();
        try
        {
            //Byg fabrik til at læse XML
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();

            //Parse XML
            Document doc = docBuilder.parse(XMLFile());

            for(String aParent : XMLParents())
            {
                NodeList children = doc.getElementsByTagName(aParent);
                for(int i = 0; i<children.getLength();i++)
                {
                    Node childElement = (Element)children.item(i);
                    if(childElement.getNodeType()==Node.ELEMENT_NODE)
                    {
                        NodeList childs = childElement.getChildNodes();
                        for(int j = 0; j<childs.getLength();j++)
                        {
                            if(!childs.item(j).toString().equals("#text"))
                                xmlValues.add(childs.item(j).getNodeName());
                        }
                    }
                }
            }
        }
        catch(Exception ex)
        {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        }

        for(int x = 0; x<xmlValues.size();x++)
        {
            if(xmlValues.get(x).equals("#text"))
            {
                xmlValues.remove("#text");
            }
        }

        return xmlValues;
    }

    protected ArrayList<String> readXMLParentValues()
    {
        ArrayList<String> parents = XMLParents();
        ArrayList<String> nodeValues = new ArrayList<String>();
        try {

            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(XMLFile());
            // normalize text representation
            doc.getDocumentElement().normalize();
            //For each parent item, get child's value
            String root = doc.getDocumentElement().getNodeName();
            for (int i = 0; i < parents.size(); i++)
            {
                Element e = doc.getDocumentElement();
                NodeList nl = doc.getElementsByTagName(root);
                for(int j = 0; j<nl.getLength();j++)
                {
                    Node n = nl.item(j);
                    if(n.getNodeType()==Node.ELEMENT_NODE)
                    {
                        Element element = (Element) n;
                        NodeList nodelist = element.getElementsByTagName(parents.get(i).trim());
                        Element element1 = (Element) nodelist.item(0);
                        NodeList nodeValue = element1.getChildNodes();
                        if(!nodeValue.item(0).getNodeValue().equals("\n\t\t"))
                            nodeValues.add(nodeValue.item(0).getNodeValue());
                    }
                }
            }

        } catch (SAXException ex) {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"SAX FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        } catch (IOException ex) {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"IO FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        } catch (ParserConfigurationException ex) {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"Parsing FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        }

        return nodeValues;
    }

    /**
     * Læser værdier i detaljesætxml.
     *
     * @return ArrayList<String>
     */
    protected ArrayList<String> readDetailSetValues()
    {
        //Dokumentation: http://stackoverflow.com/questions/773012/getting-xml-node-text-value-with-java-dom
        ArrayList<String> nodeValues = new ArrayList<String>();
        try {

            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(XMLFile());
            // normalize text representation
            doc.getDocumentElement().normalize();

            NodeList detailsRoot = doc.getElementsByTagName("Details");
            
            if(detailsRoot!= null && detailsRoot.getLength()>0)
            {
                for (int i = 0; i < detailsRoot.getLength(); i++)
                {
                    Node n = detailsRoot.item(i);
                    if(n.getNodeType()==Node.ELEMENT_NODE)
                    {
                        NodeList detailSetNL = n.getChildNodes();
                        for(int j = 0; j<detailSetNL.getLength();j++)
                        {
                            Node nv = detailSetNL.item(j);
                            if(nv.hasChildNodes())
                            {
                                NodeList valueNL = nv.getChildNodes();
                                for(int k = 0; k<valueNL.getLength();k++)
                                {
                                    Node value = valueNL.item(k);
                                    if(value.hasChildNodes())
                                    {
                                        nodeValues.add(value.getFirstChild().getNodeValue());
                                    }
                                }
                            }
                        }
                    }

                }
            }


        } catch (SAXException ex) {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"SAX FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        } catch (IOException ex) {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"IO FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        } catch (ParserConfigurationException ex) {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"Parser FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        }

        return nodeValues;
    }

    /**
     * Læser en xml fil for parent og deres children, og returnerer i en liste.
     *
     * @return ArrayList<String>
     */
    protected ArrayList<String> ReadXMLFile()
    {
        ArrayList<String> nodeValues = new ArrayList<String>();
        try {
            
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(XMLFile());
            // normalize text representation
            doc.getDocumentElement().normalize();
            //For each parent item, get child's value
            for (int i = 0; i < XMLParents().size(); i++)
            {
                NodeList parentElements = doc.getElementsByTagName(XMLParents().get(i));
                for (int j = 0; j < parentElements.getLength(); j++) {
                    Node parentElement = (Element) parentElements.item(j);
                    String value = "";
                    String tag = "";
                    NodeList childElements = parentElement.getChildNodes();
                    for (int k = 0; k < childElements.getLength(); k++) {
                        tag = childElements.item(k).getNodeName();
                        for (String c : XMLChildren()) {
                            if (!tag.equals("#text")) {
                                if (tag.equals(c)) {
                                    value = childElements.item(k).getFirstChild().getNodeValue();
                                    nodeValues.add(value);
                                }
                            }
                        }
                    }
                }
            }
            
        } catch (SAXException ex) {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"SAX FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        } catch (IOException ex) {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"IO FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        } catch (ParserConfigurationException ex) {
            try {
                ErrorLogger.writeToErrorLog(logDir+logName,"Parser FEJL: "+ex.getMessage()+"\n");
            } catch (Exception ex1){} // fejl hvis der ikke kan skrives til log kan ikke håndteres, SKRIV_TIL_OS_EVENT_LOG
        }

        return nodeValues;
    }
}
